import base64

from cryptography import x509
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives.serialization import NoEncryption
from cryptography.hazmat.primitives.serialization import pkcs12
from cryptography.x509 import load_pem_x509_certificate


def generate_private_key_and_csr(options):
    """
    生成RSA私钥
    """
    private_key = rsa.generate_private_key(
        public_exponent=65537,
        key_size=2048,
        backend=default_backend()
    )
    print('生成私钥文件...')
    with open(options["private_key_path"], "wb") as f:
        f.write(private_key.private_bytes(
            encoding=serialization.Encoding.PEM,
            format=serialization.PrivateFormat.PKCS8,
            encryption_algorithm=NoEncryption()
        ))

    """
    生成证书签名请求(CSR)
    """
    subject = x509.Name([
        x509.NameAttribute(x509.NameOID.COUNTRY_NAME, options["country_name"]),
        x509.NameAttribute(x509.NameOID.STATE_OR_PROVINCE_NAME, options["state_or_province_name"]),
        x509.NameAttribute(x509.NameOID.LOCALITY_NAME, options["locality_name"]),
        x509.NameAttribute(x509.NameOID.ORGANIZATION_NAME, options["organization_name"]),
        x509.NameAttribute(x509.NameOID.COMMON_NAME, options["common_name"]),
        x509.NameAttribute(x509.NameOID.EMAIL_ADDRESS, options["email_address"]),
    ])
    csr_builder = x509.CertificateSigningRequestBuilder().subject_name(subject)
    csr = csr_builder.sign(private_key, hashes.SHA256(), default_backend())
    print('生成CSR证书文件...')
    with open(options["csr_path"], "wb") as f:
        f.write(csr.public_bytes(serialization.Encoding.PEM))
    print("私钥和CSR证书已生成")


def generate_p12_certificate(options):
    # 读取 私钥 文件
    with open(options['private_key_path'], "rb") as f:
        private_key_data = f.read()

    # 读取证书文件
    with open(options['cert_path'], "rb") as f:
        cert_data = f.read()
    # 解析证书
    cert = x509.load_der_x509_certificate(cert_data, default_backend())
    print("证书主题：", cert.subject)
    print("证书颁发者：", cert.issuer)
    print("证书有效期开始时间：", cert.not_valid_before_utc)
    print("证书有效期结束时间：", cert.not_valid_after_utc)
    # cer 转 pem
    pem_data = base64.b64encode(cert_data).decode("utf-8")
    pem_data = "-----BEGIN CERTIFICATE-----\n" + pem_data + "\n-----END CERTIFICATE-----\n"
    pem_cert = load_pem_x509_certificate(pem_data.encode())
    # 生成私钥
    private_key = serialization.load_pem_private_key(
        private_key_data,
        password=None,
        backend=default_backend()
    )

    # 生成 P12 证书
    p12 = serialization.pkcs12.serialize_key_and_certificates(
        name=options["friendly_name"].encode(),
        key=private_key,
        cas=[pem_cert],
        cert=pem_cert,
        encryption_algorithm=serialization.BestAvailableEncryption(options["passphrase"].encode())
    )

    # 将 P12 证书保存到磁盘
    with open(options["p12_path"], "wb") as f:
        f.write(p12)

    print("P12 证书已生成, 证书密码: " + options["passphrase"])


"""
IOS生成证书, 使用方式
1. 确认并创建path目录, 建议以项目命名, 区分dev, prod目录, 确认参数, 请牢记证书信息及密码
2. 先生成 KEY, CSR 证书, 苹果创建证书需要CSR证书, 将 CSR 上传到苹果证书后 下载 CER 证书文件
3. 将下载的 CER 证书放到当前目录, 改名为 cert.cer 
4. 注释掉 generate_private_key_and_csr(options) 方法
5. 使用 generate_p12_certificate(options) 方法, 启动生成 P12 证书文件
6. 苹果创建 Profiles , 即 描述文件, 以供打包IOS使用

推荐使用 Openssl 脚本安装:
Win64 安装 Openssl, 网址: https://slproweb.com/products/Win32OpenSSL.html , 选择 Win64 OpenSSL v1.1.1w 版本, 不要选择 OpenSSL 3.x 版本
1. 生成私钥和CSR
openssl genrsa -out private.key 2048
openssl req -new -sha256 -key private.key -out csr.csr
2. 使用CSR去苹果账户换取CER证书, 将证书放到当前目录改名为 cert.cer
3. CER转PEM证书
openssl x509 -inform DER -outform PEM -in cert.cer -out pem.pem
4. 生成P12证书, 输入密码
openssl pkcs12 -inkey private.key -in pem.pem -export -out certificate.p12 

"""
if __name__ == '__main__':
    # 示例用法
    path = './cert/ceshi/dev/'
    options = {
        "private_key_path": path + "private.key",
        "csr_path": path + "csr.csr",
        "cert_path": path + "cert.cer",
        "p12_path": path + "certificate.p12",
        # 通用名称
        "common_name": "yuanxinwenhua",
        # 国家代码
        "country_name": "CN",
        # 省
        "state_or_province_name": "shandong",
        # 地区
        "locality_name": "jinan",
        # 组织名称
        "organization_name": "yuanxinwenhua",
        # 邮箱
        "email_address": "1032428119@qq.com",
        # 证书名称
        "friendly_name": "yuanxinwenhua",
        # 证书密码
        "passphrase": "yuanxinwenhua",
    }
    # 生成 key, csr证书, 注释掉P12证书生成
    # generate_private_key_and_csr(options)
    # 生成P12证书, 需将key,csr,cer证书都放在读取的目录内
    # generate_p12_certificate(options)

    # 推荐使用Shell方式, 当前方式生成的 P12 证书密码存在问题, 无法验证通过密码
